home *** CD-ROM | disk | FTP | other *** search
- //\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/
- //
- // Palette Anim.c
- //
- // Simple demonstration of Palette Animation. This method of animation is extremely useful
- // in a very narrow range of applications--certainly worthy of experimenting with and keeping
- // in mind as a solution.
- //
- // The cpu load of Palette animation is low, and you may notice that your cursor does not
- // flicker when placed over animating objects. These are both side-effects of the fact that
- // all we're really doing is moving around a very few bytes in the Palette to acheive these
- // effects. Palette animation is a keen trick, and sometimes *just* what the doctor ordered.
- //
- // History:
- //
- // 950301 jb: Written
- //
- //\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/
-
-
- // __#Defines________________________________________________________________________
- #define kMainWindowResID 1000
- #define kAppColorTableResID 1024
-
- #define kColorBoxCIndex 2 //palette entry number for our color box
- #define kColorBoxC2Index 3 //palette entry number for color box border
- #define kColorBoxLeft 10
- #define kColorBoxTop 10
- #define kColorBoxWidth 220
- #define kColorBoxHeight ((kColorBoxWidth / 5) * 3) //3x5 is nice ratio
-
- #define kFlickerBoxCIndex 4 //palette entry we'll use for this box
- #define kFlickerBoxLeft kColorBoxLeft + 8
- #define kFlickerBoxTop kColorBoxTop + 8
- #define kFlickerBoxWidth 32
- #define kFlickerBoxHeight kFlickerBoxWidth
-
- #define kChaserCIndexOffset 6 //1st chaser color at entry kChaserCIndexOffset,
- #define kNumChasers 24 //defines how many chasers we'll draw
- #define kChaserRadius 48 //max radius of chaser circle
- #define kChaserDotSize 8 //how big chaser should be
- //last at kChaserCIndexOffset + kNumChasers - 1
-
- #define kBackgroundIndex 200 //index of background color
-
- #define kDrawPaletteEntriesAtTop FALSE //draws all 256 entries in small rectangle
- //this feature is more for debugging than
- //demonstration, but is included as an
- //instructive aid.
-
- // __#Headers________________________________________________________________________
- #include <Palettes.h>
- #include <math.h> //for transcendental functions
- #include "Utils.h"
-
- // __#Protos_________________________________________________________________________
- // __ Macros_________________________________________________________________________
- // __ Enums__________________________________________________________________________
- // __ Typedefs_______________________________________________________________________
- // __ Static Protos__________________________________________________________________
- static Boolean OpenMainWindow( void );
- static void DoDemo( void );
- static void Render( void );
- static void AnimateFrame( void );
-
- // __ Extern Globals_________________________________________________________________
-
- // __ Static Globals_________________________________________________________________
- static OSErr gErr;
- static Str32 gAppName;
- static WindowPtr gMainWindow;
- static CTabHandle gOurColorTable;
- static PaletteHandle gAppPalette;
- // __ Functions______________________________________________________________________
-
-
- //____ main __________________________________________________________________________
- //
- void main( void )
- {
- ToolBoxInit();
-
- if (!EnviroCheck())
- ExitToShell();
-
- GetAppName((char *)gAppName);
-
- if (!OpenMainWindow())
- ExitToShell();
-
- DoDemo();
-
- if(NULL != gMainWindow)
- DisposeWindow(gMainWindow);
- if(NULL != gOurColorTable)
- DisposeCTable(gOurColorTable);
- }//main
-
-
- //____ OpenMainWindow __________________________________________________________________________
- //
- // Open our window, install palette from a resource CTable.
- //
- static Boolean OpenMainWindow( void )
- {
- // create and show the window, make sure it's frontmost
- gMainWindow = GetNewCWindow( kMainWindowResID, ( Ptr )NULL, ( WindowPtr ) -1 );
- if (NULL == gMainWindow) //real apps should handle this gracefully
- return FALSE;
- SetWTitle(gMainWindow,gAppName);
-
- //FYI: Animating offscreen palettes:
- //Setting bit 14 of an offscreen's color table gives us a way to refer to palette
- //indexes instead of RGB values. The value[x] fields of the color table describe
- //which palette entry to use when drawing pixels with index x. This makes it
- //possible to use animated colors in an offscreen world. See "Palette Manager Animation,"
- //by Rich Collyer in the Winter, 1991 issue of "develop" from Apple.
- // (**gOurColorTable).ctFlags |= 0x4000; //see Inside Mac VI pp 20-14
-
- //load in the color table, translate to palette, install in window
- gOurColorTable = GetCTable( kAppColorTableResID );
- if (NULL == gOurColorTable)
- return FALSE;
-
- gAppPalette = NewPalette( 256, gOurColorTable, pmExplicit + pmTolerant, 0x0000 );
-
- NSetPalette( gMainWindow, gAppPalette, pmAllUpdates );
-
- ActivatePalette(gMainWindow);
-
- ShowWindow( gMainWindow );
- SetPort( gMainWindow );
-
- //give us a nice, neutral background
- PmForeColor(kBackgroundIndex);
- PaintRect(&qd.thePort->portRect);
-
- return TRUE;
- }//OpenMainWindow
-
-
-
-
- //____ DoDemo __________________________________________________________________________
- //
- // Nifty function shows off some ways to do Palette Animation
- //
- // Returns void
- //
- static void DoDemo( void )
- {
- Boolean done;
- EventRecord theEvent;
-
- done = FALSE;
- while (!done)
- {
- if(WaitNextEvent(everyEvent, &theEvent, 0L, 0L))
- {
- switch (theEvent.what)
- {
- case mouseDown:
- case keyDown:
- done = TRUE;
- case updateEvt:
- if ((WindowPtr) theEvent.message == gMainWindow)
- {
- BeginUpdate(gMainWindow);
- Render();
- AnimateFrame();
- EndUpdate(gMainWindow);
- }
- break;
- }//switch (theEvent.what)
- }//if WaitNextEvent
-
- AnimateFrame();
-
- }//while
-
- }//DoDemo
-
-
- //____ Render __________________________________________________________________________
- //
- // Draw objects using PmForeColor.
- //
- static void Render( void )
- {
- #define kDrawText TRUE //draws nicely-colored text in background
-
- #define mThetaStepSize (6.283 / kNumChasers) //how far around our circle to go
- #define kChaserHalfDotSize kChaserDotSize / 2 //make it easy to center chaser on point
-
- short step;
- short x, y, cenX, cenY;
- double theta;
- Rect aRect;
-
- #if kDrawText
- Handle txtHdl;
- long len;
- short fontNum;
- #endif
-
- //Make our special colors animated
- for (x = 2; x <= kBackgroundIndex; x++)
- {
- SetEntryUsage(gAppPalette, x, pmAnimated + pmExplicit, 0x0000);
- }
- for (x = kBackgroundIndex + 1; x < 256; x++) //be nice to environment
- {
- SetEntryUsage(gAppPalette, x, pmTolerant, 0x7000);
- }
-
- #if kDrawText
- //draw our text; note that it doesn't animate, even
- //though it's drawn with the same index as the color
- //box's frame, which *does* animate.
- txtHdl = GetResource('TEXT', 128);
- if (NULL != txtHdl)
- {
- len = GetHandleSize(txtHdl);
- HLock(txtHdl);
- GetFNum("\ppalatino",&fontNum); //if palatino not found, fontNum == 0 == System font
- TextFont(fontNum);
- TextSize(12);
-
- //draw our text
- PmForeColor(kColorBoxC2Index);
- PmBackColor(kBackgroundIndex);
- aRect = gMainWindow->portRect;
- aRect.right += 10000; //avoid wrapping
- TextBox(*txtHdl, len, &aRect, teJustLeft);
-
- ReleaseResource(txtHdl);
- }
- #endif //kDrawText
-
-
- #if kDrawPaletteEntriesAtTop
- //draw all palette entries at top
- for (x = 0; x < 256; x++)
- {
- PmForeColor(x);
- MoveTo(x, 0);
- Line(0, 4);
- }
- #endif
-
- //draw colorBox
- SetRect(&aRect, kColorBoxLeft, kColorBoxTop,
- kColorBoxLeft+kColorBoxWidth, kColorBoxTop+kColorBoxHeight);
-
- PmForeColor(kColorBoxC2Index); //draw border
- PaintRect(&aRect);
- InsetRect(&aRect, 2, 2);
- PmForeColor(kColorBoxCIndex);
- PaintRect(&aRect);
-
- //draw flicker box
- SetRect(&aRect, kFlickerBoxLeft, kFlickerBoxTop,
- kFlickerBoxLeft + kFlickerBoxWidth, kFlickerBoxTop + kFlickerBoxHeight);
- PmForeColor(kFlickerBoxCIndex);
- PaintRect(&aRect);
- PmForeColor(251);
- FrameRect(&aRect);
-
- //center our chasers on lower right corner of colorBox
- cenX = kColorBoxLeft+kColorBoxWidth;
- cenY = kColorBoxTop+kColorBoxHeight;
-
- //draw circle of chasers
- for (step = 0, theta = 0.0; step < kNumChasers; step++)
- {
- theta += mThetaStepSize;
- x = cenX + kChaserRadius * cos(theta);
- y = cenY - kChaserRadius * sin(theta);
-
- PmForeColor(kChaserCIndexOffset + step);
- SetRect(&aRect, x - kChaserHalfDotSize, y - kChaserHalfDotSize, x + kChaserHalfDotSize, y + kChaserHalfDotSize);
- PaintOval(&aRect);
- }
-
- //we've changed our palette, make sure the hardware knows about it!
- ActivatePalette(gMainWindow);
-
- }//Render
-
-
- //____ AnimateFrame __________________________________________________________________________
- //
- // Called at regular intervals, this function manipulates pmAnimated colors in the
- // Palette to create various sorts of color-cycling animaiton.
- //
- static void AnimateFrame( void )
- {
- #define kNumHSVSteps 200 //used to create new colors to
- #define mHSVThetaStep (65535 / kNumHSVSteps) //pop into Palette
-
- static HSVColor boxHSV = {0, 65535, 65535};
- static HSVColor frameHSV = {32767, 65535, 65535};
- static double hsvTheta;
- static Boolean flickWhite = FALSE;
- static RGBColor whiteRGB = {65535, 65535, 65535};
- static RGBColor blackRGB = {0, 0, 0};
- RGBColor tempRGB;
-
- //change color of our color box
- boxHSV.hue += mHSVThetaStep; //move clockwise along color wheel for next color
- HSV2RGB(&boxHSV,&tempRGB); //translate to RGB
- AnimateEntry(gMainWindow, kColorBoxCIndex, &tempRGB); //replace old color with new one
-
- //change color of our color box's border
- frameHSV.hue += mHSVThetaStep;
- HSV2RGB(&frameHSV,&tempRGB);
- AnimateEntry(gMainWindow, kColorBoxC2Index, &tempRGB);
-
- //draw annoying, flickering box
- flickWhite = !flickWhite;
- if (flickWhite)
- AnimateEntry(gMainWindow, kFlickerBoxCIndex, &whiteRGB);
- else
- AnimateEntry(gMainWindow, kFlickerBoxCIndex, &blackRGB);
-
-
-
- //here, we'll cause cycling by shifting our array of colors over 1, making sure
- //that the color in 1st bucket gets stuck on the other end.
- GetEntryColor(gAppPalette, kChaserCIndexOffset, &tempRGB); //get 1st color
- AnimatePalette(gMainWindow, gOurColorTable, //bump colors down 1
- kChaserCIndexOffset + 1, kChaserCIndexOffset, kNumChasers);
- AnimateEntry(gMainWindow, kChaserCIndexOffset + kNumChasers, &tempRGB); //pop saved color
- //onto end of array
- Palette2CTab(gAppPalette, gOurColorTable); //grab color table, now
- //that it's been modified
-
- }//AnimateFrame